﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Web;
using Gizmox.WebGUI.Forms;
using GuiLabs.Undo;

namespace Bronze.ReportBuilder.Actions
{
    /// <summary>
    /// This is a sample action that can change any property on any object
    /// It can also undo what it did
    /// </summary>
    public class SetPropertyAction : AbstractAction
    {
        public SetPropertyAction(object parentObject, string propertyName, object value)
        {
            ParentObject = parentObject;
            Property = parentObject.GetType().GetProperty(propertyName);
            Value = value;
        }

        public object ParentObject { get; set; }
        public PropertyInfo Property { get; set; }
        public object Value { get; set; }
        public object OldValue { get; set; }

        protected override void ExecuteCore()
        {
            OldValue = Property.GetValue(ParentObject, null);
            Property.SetValue(ParentObject, Value, null);
        }

        protected override void UnExecuteCore()
        {
            Property.SetValue(ParentObject, OldValue, null);
        }

        /// <summary>
        /// Subsequent changes of the same property on the same object are consolidated into one action
        /// </summary>
        /// <param name="followingAction">Subsequent action that is being recorded</param>
        /// <returns>true if it agreed to merge with the next action, 
        /// false if the next action should be recorded separately</returns>
        public override bool TryToMerge(IAction followingAction)
        {
            var next = followingAction as SetPropertyAction;
            if (next != null && next.ParentObject == this.ParentObject && next.Property == this.Property)
            {
                Value = next.Value;
                Property.SetValue(ParentObject, Value, null);
                return true;
            }
            return false;
        }
    }



    public class PropertyChangeAction : AbstractAction
    {
        private readonly FormDesigner _designer;
        private readonly Control _control;

        private readonly PropertyDescriptor _property;
        private object _value;
        private bool _needSetValue;

        
        public Action CallBack;


        public PropertyChangeAction(FormDesigner designer,Control control, PropertyDescriptor property, object value)
        {
            this._designer = designer;
            this._control = control;
            this._property = property;
            this._value = value;
        }


        protected override void ExecuteCore()
        {
            _designer.TrackProperty(_control,_property.Name);
            if (!_needSetValue) return;


            var value = _property.GetValue(_control);
            _property.SetValue(_control, _value);

            this._value = value;
            if (CallBack!=null)
            {
                CallBack();
            }
        }

        protected override void UnExecuteCore()
        {
            _needSetValue = true;
            this.ExecuteCore();
            if (CallBack != null)
            {
                CallBack();
            }
        }
    }


}